<!-- CodeEditor.vue -->
<template>
  <div class="code-editor-wrapper">
    <div ref="editorRef" class="editor"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
import { EditorView, basicSetup, minimalSetup } from 'codemirror';
import { EditorState, Compartment } from '@codemirror/state';
import { lineNumbers, keymap } from '@codemirror/view';
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
import { indentWithTab } from '@codemirror/commands';
import { bracketMatching, defaultHighlightStyle } from '@codemirror/language';
import { javascript } from '@codemirror/lang-javascript';
import { html } from '@codemirror/lang-html';
import { css } from '@codemirror/lang-css';
import { json } from "@codemirror/lang-json"

// 定义 props
const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  language: {
    type: String,
    default: 'javascript', // 支持: javascript, html, css
    validator: (value) => ['json'].includes(value),
  },
  readOnly: {
    type: Boolean,
    default: false,
  },
  theme: {
    type: String,
    default: 'light', // 可扩展为暗色主题
  },
  showGutter: {
    type: Boolean,
    default: true,
  },
});

// 定义 emit 事件
const emit = defineEmits(['update:modelValue', 'change', 'ready']);

// 编辑器 DOM 引用
const editorRef = ref(null);
// CodeMirror 实例
let view = null;
const gutterCompartment = new Compartment;

// 根据语言选择对应的扩展
const getLanguageExtension = () => {
  switch (props.language) {
    case 'html':
      return html();
    case 'css':
      return css();
    case 'json':
      return json();
    case 'javascript':
    default:
      return javascript();
  }
};

// 创建编辑器
const createEditor = () => {
  const startState = EditorState.create({
    doc: props.modelValue || '',
    extensions: [
      minimalSetup,
      getLanguageExtension(),
      gutterCompartment.of(props.showGutter ? lineNumbers() : []),
      // props.showLineNumbers ? lineNumbers() : null,
      // bracketMatching(),
      // defaultHighlightStyle.fallback,
      // history(),
      // keymap.of([
      //   ...defaultKeymap,
      //   ...historyKeymap,
      //   indentWithTab,
      // ]),
      EditorState.readOnly.of(props.readOnly),
      EditorView.updateListener.of((update) => {
        if (update.docChanged) {
          const value = update.state.doc.toString();
          emit('update:modelValue', value);
          emit('change', value);
        }
      }),
      // EditorView.theme({
      //   '&': {
      //     height: '100%',
      //     fontSize: '14px',
      //     fontFamily: 'monospace',
      //   },
      //   '.cm-content': {
      //     padding: '8px 12px',
      //     minHeight: '200px',
      //   },
      //   '.cm-gutters': {
      //     backgroundColor: 'transparent',
      //     borderRight: 'none',
      //   },
      // }),
    ],
  });

  view = new EditorView({
    state: startState,
    parent: editorRef.value,
  });

  emit('ready', view);
};

// 监听 modelValue 变化（外部更新）
watch(
  () => props.modelValue,
  (newValue, oldValue) => {
    if (view && newValue !== oldValue) {
      // 避免无限循环
      const currentValue = view.state.doc.toString();
      if (newValue !== currentValue) {
        const transaction = view.state.update({
          changes: { from: 0, to: currentValue.length, insert: newValue },
        });
        view.dispatch(transaction);
      }
    }
  }
);

// 监听 language 变化
watch(
  () => props.language,
  () => {
    if (view) {
      view.setState(
        EditorState.create({
          doc: view.state.doc.toString(),
          extensions: [
            basicSetup,
            getLanguageExtension(),
            // ... 其他扩展
            EditorView.updateListener.of((update) => {
              if (update.docChanged) {
                const value = update.state.doc.toString();
                emit('update:modelValue', value);
                emit('change', value);
              }
            }),
            // ... 保持其他配置
          ],
        })
      );
    }
  }
);

// 组件挂载后创建编辑器
onMounted(async () => {
  await nextTick(); // 确保 DOM 渲染完成
  if (editorRef.value) {
    createEditor();
  }
});

// 组件卸载时销毁编辑器
onUnmounted(() => {
  if (view) {
    view.destroy();
    view = null;
  }
});
</script>

<style scoped>
.code-editor-wrapper {
  position: relative;
  border: 1px solid #ddd;
  border-radius: 4px;
  overflow: hidden;
  background-color: #fff;
  display: flex;
}

.editor {
  flex: 1;
  min-height: 200px;
}

.line-numbers {
  width: 40px;
  text-align: right;
  padding: 8px 8px 8px 4px;
  font-size: 12px;
  color: #999;
  background-color: #f7f7f7;
  border-right: 1px solid #ddd;
  user-select: none;
}

.line-numbers .current-line {
  font-weight: bold;
  color: #000;
}
</style>